﻿//////////////////////////////////////////////////////////////////////////////
//
// Copyright © 1998-2024 Glodon Company Limited.
//
// Licensed under the MIT License
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the “Software”),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
//////////////////////////////////////////////////////////////////////////////
#pragma once

#include "GbmpModel.h"
#include "NdbObjectSchematic.h"
#include "NdbDataSchema.h"
#include "ISurface.h"
#include "Matrix4d.h"



namespace gcmp
{
    class IElement;

    // 端点参数域
    class GBMP_MODEL_EXPORT TerminalParams : public NdbObjectSchematic
    {
        DATA_BEGIN(gcmp, TerminalParams, gcmp::NdbObjectSchematic, D9DDB51E - 6EA5 - 4A67 - A08D - 89C45CD3E5B2, gbmpmodel)
            DATA(double, StartRangeU)
            DATA(double, MidRangeU)
            DATA(double, EndRangeU)
            DATA(double, StartRangeV)
            DATA(double, MidRangeV)
            DATA(double, EndRangeV)
        DATA_END

    public:
        static TerminalParams Create(double startRangeU, double midRangeU, double endRangeU, double startRangeV, double midRangeV, double endRangeV);
        virtual ~TerminalParams() {}

        double GetStartRangeU() const { return this->GetStartRangeU__(); }
        bool SetStartRangeU(double val) { this->SetStartRangeU__(val); return true; }

        double GetMidRangeU() const { return this->GetMidRangeU__(); }
        bool SetMidRangeU(double val) { this->SetMidRangeU__(val); return true; }

        double GetEndRangeU() const { return this->GetEndRangeU__(); }
        bool SetEndRangeU(double val) { this->SetEndRangeU__(val); return true; }

        double GetStartRangeV() const { return this->GetStartRangeV__(); }
        bool SetStartRangeV(double val) { this->SetStartRangeV__(val); return true; }

        double GetMidRangeV() const { return this->GetMidRangeV__(); }
        bool SetMidRangeV(double val) { this->SetMidRangeV__(val); return true; }

        double GetEndRangeV() const { return this->GetEndRangeV__(); }
        bool SetEndRangeV(double val) { this->SetEndRangeV__(val); return true; }

        Intervald GetRangeU(bool& bSameDirection) const;
        Intervald GetRangeV(bool& bSameDirection) const;

        std::wstring GetRangeUDebugString() const; 
        std::wstring GetRangeVDebugString() const; 

    public: //实现NdbObject接口
        virtual NdbObject* GetTopOwnerObject() const override
        {
            return nullptr;
        }
    };

    class ICurve2d;
    class ILine2d;
    class IArc2d;

    // 有界基准曲面
    class GBMP_MODEL_EXPORT SurfaceAndTerminals : public NdbObjectSchematic
    {
        DATA_BEGIN(gcmp, SurfaceAndTerminals, gcmp::NdbObjectSchematic, AFA6B6EF - 51ED - 4BA9 - B6C6 - 51AC855DF016, gbmpmodel)
            DATA(OwnerPtr<ISurface>, DatumSurface) // 基准曲面
            DATA(TerminalParams, GlobalTerminalParams) // 全局边界参数域
            UMAP_DATA(ElementId, TerminalParams, ElementIdHash, LocalTerminalParams) // 视图重载边界参数域
        DATA_END
    
    public:
        virtual ~SurfaceAndTerminals() {}

        static OwnerPtr<SurfaceAndTerminals> Create(const ICurve2d* pCurve2d, const Intervald& rangeV, const Vector3d& dirV = Vector3d::UnitZ);
        static OwnerPtr<SurfaceAndTerminals> CreateAsPlane(const ILine2d* pLine2d, const Intervald& rangeV, const Vector3d& dirV = Vector3d::UnitZ);
        static OwnerPtr<SurfaceAndTerminals> CreateAsCylinder(const IArc2d* pArc2d, const Intervald& rangeV, const Vector3d& dirV = Vector3d::UnitZ);

        const ISurface* GetSurfaceReference() const { return this->GetDatumSurface__().get(); }
        bool IsPlanar() const;
        bool IsCylindric() const;

        TerminalParams GetGlobalTerminalParams() const { return this->GetGlobalTerminalParams__(); }
        bool SetGlobalTerminalParams(const TerminalParams& params) { this->SetGlobalTerminalParams__(params); return true; }
        OwnerPtr<ISurface> GetGlobalSurface() const { return this->GetSurface(this->GetGlobalTerminalParams()); }

        bool HasLocalTerminalParams() const; 
        bool HasLocalTerminalParams(ElementId modelviewId) const;
        TerminalParams GetLocalTerminalParams(ElementId modelviewId) const;
        bool AddOrUpdateLocalTerminalParams(ElementId modelviewId, const TerminalParams& params);
        bool DeleteAllLocalTerminalParams();
        bool DeleteLocalTerminalParams(ElementId modelviewId);

        OwnerPtr<ISurface> GetLocalSurface(ElementId modelviewId) const { return this->GetSurface(this->GetLocalTerminalParams(modelviewId)); }

        bool PerformTranform(const Matrix4d& mat); 

    public: //实现NdbObject接口
        virtual NdbObject* GetTopOwnerObject() const override
        {
            return nullptr;
        }

    private:
        OwnerPtr<ISurface> GetSurface(const TerminalParams& params) const;
    };

}// namespace gcmp
